package logger

import (
	"fmt"
)

type Level int8

const (
	TraceLevel Level = iota - 2
	DebugLevel
	InfoLevel
	WarnLevel
	ErrorLevel
	FatalLevel
)

func (l Level) String() string {
	switch l {
	case TraceLevel:
		return "trace"
	case DebugLevel:
		return "debug"
	case InfoLevel:
		return "info"
	case WarnLevel:
		return "warn"
	case ErrorLevel:
		return "error"
	case FatalLevel:
		return "fatal"
	}
	return ""
}

func (l Level) LevelForGorm() int {
	switch l {
	case FatalLevel, ErrorLevel:
		return 2
	case WarnLevel:
		return 3
	case InfoLevel, DebugLevel, TraceLevel:
		return 4
	default:
		return 1
	}
}

func (l Level) Enabled(lvl Level) bool {
	return lvl >= l
}

func GetLevel(levelStr string) (Level, error) {
	switch levelStr {
	case TraceLevel.String():
		return TraceLevel, nil
	case DebugLevel.String():
		return DebugLevel, nil
	case InfoLevel.String():
		return InfoLevel, nil
	case WarnLevel.String():
		return WarnLevel, nil
	case ErrorLevel.String():
		return ErrorLevel, nil
	case FatalLevel.String():
		return FatalLevel, nil
	}
	return InfoLevel, fmt.Errorf("Unknown Level String: '%s', defaulting to InfoLevel", levelStr)
}

func Info(args ...any) {
	DefaultLogger.Log(InfoLevel, args...)
}

func Trace(args ...any) {
	DefaultLogger.Log(TraceLevel, args...)
}

func Debug(args ...any) {
	DefaultLogger.Log(DebugLevel, args...)
}

func Warn(args ...any) {
	DefaultLogger.Log(WarnLevel, args...)
}

func Error(args ...any) {
	DefaultLogger.Log(ErrorLevel, args...)
}

func Fatal(args ...any) {
	DefaultLogger.Log(FatalLevel, args...)
}

func Infof(format string, args ...any) {
	DefaultLogger.Logf(InfoLevel, format, args...)
}

func Tracef(format string, args ...any) {
	DefaultLogger.Logf(TraceLevel, format, args...)
}

func Debugf(format string, args ...any) {
	DefaultLogger.Logf(DebugLevel, format, args...)
}

func Warnf(format string, args ...any) {
	DefaultLogger.Logf(WarnLevel, format, args...)
}

func Errorf(format string, args ...any) {
	DefaultLogger.Logf(ErrorLevel, format, args...)
}

func Fatalf(format string, args ...any) {
	DefaultLogger.Logf(FatalLevel, format, args...)
}

func V(lvl Level, log Logger) bool {
	l := DefaultLogger
	if log != nil {
		l = log
	}
	return l.Options().Level <= lvl
}
